import BaseOAuthProvider from "./base-provider";
import type { OAuthConfig } from "./base-provider";
import axios from 'axios';
import { OAuthUserInfo } from "@/service/oauthService";

/**
 * GitHub OAuth Provider
 * 实现 GitHub OAuth 2.0 认证流程
 */
class GitHubProvider extends BaseOAuthProvider {
    authUrl: string;
    tokenUrl: string;
    userInfoUrl: string;

    constructor(config: OAuthConfig) {
        super(config);
        this.authUrl = 'https://github.com/login/oauth/authorize';
        this.tokenUrl = 'https://github.com/login/oauth/access_token';
        this.userInfoUrl = 'https://api.github.com/user';
    }

    /**
     * 交换授权码获取访问令牌
     */
    async exchangeCodeForTokens(code: string) {
        try {
            const params = {
                client_id: this.clientId,
                client_secret: this.clientSecret,
                code: code,
                redirect_uri: this.redirectUri
            };

            const response = await axios.post(this.tokenUrl, params, {
                headers: {
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                },
                timeout: 10000 // 10秒超时
            });

            // GitHub 可能返回不同格式的响应
            const data = response.data;

            // 检查是否有错误
            if (data.error) {
                throw new Error(`GitHub OAuth error: ${data.error_description || data.error}`);
            }

            // 验证响应数据
            if (!data.access_token) {
                throw new Error('No access token received from GitHub');
            }

            return data;
        } catch (error: any) {
            if (error.response) {
                // GitHub API返回的错误
                const errorData = error.response.data;
                let errorMessage = error.message;

                if (typeof errorData === 'string') {
                    // GitHub 有时返回 URL 编码的错误信息
                    const urlParams = new URLSearchParams(errorData);
                    const errorDesc = urlParams.get('error_description') || urlParams.get('error');
                    if (errorDesc) {
                        errorMessage = errorDesc;
                    }
                } else if (errorData.error) {
                    errorMessage = errorData.error_description || errorData.error;
                }

                throw new Error(`GitHub token exchange failed: ${errorMessage} (HTTP ${error.response.status})`);
            } else if (error.request) {
                // 网络错误
                throw new Error(`GitHub token exchange failed: Network error - ${error.message}`);
            } else {
                // 其他错误
                throw new Error(`GitHub token exchange failed: ${error.message}`);
            }
        }
    }

    /**
     * 获取用户信息
     */
    async getUserInfo(accessToken: string) {
        try {
            // 获取基本用户信息
            const userResponse = await axios.get(this.userInfoUrl, {
                headers: {
                    'Authorization': `Bearer ${accessToken}`,
                    'Accept': 'application/vnd.github.v3+json',
                    'User-Agent': 'OAuth-App' // GitHub API 要求 User-Agent
                },
                timeout: 10000
            });

            const userData = userResponse.data;
            // 验证响应数据
            if (!userData.id) {
                throw new Error('Invalid user info received from GitHub');
            }

            // 如果用户没有公开邮箱，尝试获取邮箱信息
            let userEmail = userData.email;
            if (!userEmail) {
                try {
                    const emailResponse = await axios.get('https://api.github.com/user/emails', {
                        headers: {
                            'Authorization': `Bearer ${accessToken}`,
                            'Accept': 'application/vnd.github.v3+json',
                            'User-Agent': 'OAuth-App'
                        },
                        timeout: 5000
                    });

                    // 查找主邮箱或已验证的邮箱
                    const emails = emailResponse.data;
                    const primaryEmail = emails.find((email: any) => email.primary && email.verified);
                    const verifiedEmail = emails.find((email: any) => email.verified);

                    userEmail = primaryEmail?.email || verifiedEmail?.email || emails[0]?.email;
                } catch (emailError) {
                    // 邮箱获取失败不影响主流程，继续处理
                    console.warn('Failed to fetch GitHub user emails:', emailError);
                }
            }

            return {
                ...userData,
                email: userEmail
            };
        } catch (error: any) {
            if (error.response) {
                // GitHub API返回的错误
                const status = error.response.status;
                if (status === 401) {
                    throw new Error('GitHub user info fetch failed: Invalid or expired access token');
                } else if (status === 403) {
                    throw new Error('GitHub user info fetch failed: Rate limit exceeded or insufficient permissions');
                } else {
                    throw new Error(`GitHub user info fetch failed: HTTP ${status}`);
                }
            } else if (error.request) {
                // 网络错误
                throw new Error('GitHub user info fetch failed: Network error');
            } else {
                // 其他错误
                throw new Error(`GitHub user info fetch failed: ${error.message}`);
            }
        }
    }

    /**
     * 处理用户数据，转换为统一格式
     */
    processUserData(userInfo: any): OAuthUserInfo {
        // 处理用户姓名的逻辑
        let name = userInfo.name;
        if (!name && userInfo.login) {
            name = userInfo.login; // GitHub 用户名作为备选
        } else if (!name && userInfo.email) {
            name = userInfo.email.split('@')[0];
        } else if (!name) {
            name = 'GitHub User';
        }

        // GitHub 用户可能没有邮箱，使用 login 作为备选
        const email = userInfo.email || `${userInfo.login}@github.local`;

        return {
            id: userInfo.id.toString(), // 确保ID是字符串
            email: email,
            name: name,
            avatar: userInfo.avatar_url || undefined,
        };
    }
}

export default GitHubProvider;
